"""This module holds function take out list unions, intersection, difference.
Requirement of this module is that the elements of the set should have
the == comparator defined
"""


def list_union(l1, l2, comparision_items=None):
    """This function returns the combination of all elements between the two 
    lists avoiding duplicates
    """
    s1 = set(l1)
    s2 = set(l2)
    s1 = s1.union(s2)
    return list(s1)


def list_intersection(l1, l2):
    """This function returns all the common elements between the two lists
    """
    s1 = set(l1)
    s2 = set(l2)
    s1 = s1.intersection(s2)
    return list(s1)


def list_intersection_opp(l1, l2):
    """This function returns all the elements which are either in l1 or l2, 
    but not in both
    """
    s1 = set(l1)
    s2 = set(l2)
    s1 = s1.symmetric_difference(s2)
    return list(s1)


def list_diff(l1, l2):
    """This function returns all the elements in l1 which are not present in
    l2. In set language l1 - l2
    """
    s1 = set(l1)
    s2 = set(l2)
    s1 = s1.difference(s2)
    return list(s1)


def list_pos(l1, x):
    """Given a sorted list, this function finds pos, the first location of x 
    such that l1[pos-1] <= x < l1[pos]. If x needs to be inserted at the right 
    sorted location at can be then done by l1.insert(pos, x). The user needs to
    ensure that the list is sorted.
    """
    # if x would be the smallest element in l1
    if len(l1) == 0 or x < l1[0]:
        return 0
    
    # checking the rest of the list
    for idx in range(1, len(l1)):
        if l1[idx - 1] <= x and x < l1[idx]:
            return idx
    
    # if the element was greater than the last element in the list
    return len(l1)



if __name__ == '__main__':
    #main for unit testing
    l1 = [1,2,3]
    l2 = [5,1,4,2]
    print(list_union(l1, l2))
    print(list_intersection(l1, l2))
    print(list_intersection_opp(l1, l2))
    print(list_diff(l2, l1))
    
    # check list_pos function
    l2.sort()
    print(l2)
    print(list_pos(l2,0))
    print(list_pos(l2,3))
    print(list_pos(l2,5))
    